package com.cloudkinto.service.platform.impl;

import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.RabbitQueueConstant;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.CsvUtils;
import com.cloudkinto.common.utils.TimeUtils;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.dao.AsyncJobDao;
import com.cloudkinto.dao.PlatformOrderDao;
import com.cloudkinto.dao.PlatformOrderProductDao;
import com.cloudkinto.dao.ProductDao;
import com.cloudkinto.dto.platform.order.PlatOrderPageRes;
import com.cloudkinto.entity.AsyncJobDo;
import com.cloudkinto.entity.PlatformOrderDo;
import com.cloudkinto.entity.PlatformOrderProductDo;
import com.cloudkinto.entity.ProductDo;
import com.cloudkinto.service.job.AsyncJobService;
import com.cloudkinto.service.platform.PlatformOrderExportService;
import com.cloudkinto.service.platform.vo.AsyncFinishConsumerReq;
import com.cloudkinto.service.platform.vo.AsyncUpdateConsumerReq;
import com.cloudkinto.service.platform.vo.PlatOrderExportConsumerReq;
import com.cloudkinto.service.platform.vo.order.PlatformOrderNewExportVo;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
@RequiredArgsConstructor
public class PlatformOrderExportServiceImpl extends ServiceImpl<PlatformOrderDao, PlatformOrderDo>  implements PlatformOrderExportService {
    // 注入所需的DAO和工具类
    private final PlatformOrderDao dao;
    private final PlatformOrderProductDao platformOrderProductDao;
    private final AsyncJobDao asyncJobDao;
    private final RabbitTemplate rabbitTemplate;
    private final ProductDao productDao;
    @Value("${gbc.exportPath.omsFilePath}")
    private String omsFilePath;
    @Value("${gbc.uploadPath.omsFileUrl}")
    private String omsFileUrl;
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;
    private final RedisTemplate redisTemplate;
    @Value("${gbc.customer}")
    private String customer;

    // 接收导出请求，返回任务ID
    @Override
    public Long requestExport(Map<String, Object> map) {
        Object ids = map.get("ids");
        String timeName = "";
        if (ids == null) {
            Date beginTime = DateUtils.stringFormatToDate(map.get("beginTime").toString());
            Date endTime = DateUtils.passingDate(DateUtils.stringFormatToDate(map.get("endTime").toString()), 1);
            //判断天数不要大于60填
            if (DateUtils.differentDaysByMillisecond(beginTime, endTime) > 60) {
                throw new BizException("导出时间间隔不能大于60天");
            }
            timeName = DateUtils.dateFormatToString(beginTime) + "至" + DateUtils.dateFormatToString(endTime);
        }
        String createByName = map.getOrDefault("createByName", "system").toString();
        Integer count = asyncJobDao.selectCount(new LambdaQueryWrapper<AsyncJobDo>().eq(AsyncJobDo::getJobType, "EXPORT_PLATFORM_ORDER")
                .in(AsyncJobDo::getStatus, 0, 1)
                .gt(AsyncJobDo::getCreateTime, DateUtils.passingDateHour(new Date(), -1))
                .eq(AsyncJobDo::getCompanyId, map.get("companyId"))
                .eq(AsyncJobDo::getCreateBy, createByName));
        if (count > 1) {
            throw new BizException("您有正在处理的导出任务，请勿重复创建");
        }
        AsyncJobDo asyncJobDo = new AsyncJobDo();
        asyncJobDo.setStatus(0);
        asyncJobDo.setCompanyId((Long) map.get("companyId"));
        asyncJobDo.setJobType("EXPORT_PLATFORM_ORDER");
//        String name = DateUtils.dateFormatToString(DateUtils.stringFormatToDate(map.get("beginTime").toString())) + "至" + DateUtils.dateFormatToString(DateUtils.passingDate(DateUtils.stringFormatToDate(map.get("endTime").toString()), 1));
        asyncJobDo.setJobName("平台订单导出-" + timeName);
        asyncJobDo.setCreateTime(new Date());
        asyncJobDo.setCreateBy(createByName);
        asyncJobDao.insert(asyncJobDo);
        // 异步执行导出任务
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_PlatformOrder, JSON.toJSONString(new PlatOrderExportConsumerReq(asyncJobDo.getId(), map)));
//        exportAsync(map, asyncJobDo.getId());
        return asyncJobDo.getId();
    }

    // 异步导出方法
    public CompletableFuture<Void> exportAsync(Map<String, Object> map, Long taskId) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        AsyncJobDo asyncJobDo = asyncJobDao.selectById(taskId);
        if (asyncJobDo == null) {
            future.complete(null);
            return future;
        }
        rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(taskId, 1, 0, null)));
        String fileName = asyncJobDo.getJobName() +"_" + taskId + ".csv";
        boolean idsFlag = map.get("ids") != null;
        try {
            // 分页处理数据
            int pageSize = 10000;
            int pageNum = 1;
            boolean hasMoreData = true;

            // 创建临时文件
            String tempFilePath = omsFilePath + fileName;
            CsvExportParams csvParam = new CsvExportParams();
//            csvParam.setEncoding("Shift-JIS");
            csvParam.setEncoding("UTF-8");
            csvParam.setTextMark("");

            Map<String, String> fieldMap = new HashMap<>();
            // 初始化CSV文件
            CsvUtils.initCsv(tempFilePath, csvParam, PlatformOrderNewExportVo.class);

            while (hasMoreData) {
                // 设置分页参数
//                map.put("current", pageNum);
                if (!idsFlag) {
                    map.put("pageSize", pageSize);
                    map.put("offset", (pageNum - 1) * pageSize);
                }
                // 获取当前页数据
//                Page<PlatOrderPageRes> page = pageInit(map);
                List<PlatOrderPageRes> list = dao.getList(map);
//                List<PlatOrderPageRes> list = result.getRecords();
                if (list.isEmpty()) {
                    hasMoreData = false;
                    continue;
                }
                // 处理当前页数据
                List<PlatformOrderNewExportVo> exportVos = processPageData(list);
                // 追加到CSV文件
                CsvUtils.appendToCsv(tempFilePath, exportVos);

                // 更新进度
                rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(taskId, null, list.size(), null)));
                pageNum++;
                if (idsFlag) {
                    hasMoreData = false;
                }
            }


            //本机文件传到oms上
            String objectNameTemporary = "";
            if (filePath.startsWith("http")) {
                try {
                    objectNameTemporary = AliOss.temporaryFile2(fileName, new File(tempFilePath));
                } catch (Exception e) {
                    log.error("导出文件失败" + e.getMessage());
                    rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(taskId, 4, 0, "上传到oss失败")));
                    future.completeExceptionally(e);
                    return future;
                }
            }
            //文件路径
            String path = fileUrl + objectNameTemporary;
            //保存到linux本地 就打开下方注解
//            String path = omsFileUrl + fileName;
            // 完成导出，保存文件路径
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Finish, JSON.toJSONString(new AsyncFinishConsumerReq(taskId, path)));
            future.complete(null);

        } catch (Exception e) {
            // 导出失败
            rabbitTemplate.convertAndSend(RabbitQueueConstant.Export_AsyncDo_Update, JSON.toJSONString(new AsyncUpdateConsumerReq(taskId, 4, 0, e.getMessage())));
            future.completeExceptionally(e);
        }
        return future;
    }

    private Page<PlatOrderPageRes> pageInit(Map<String, Object> map) {
        int size = map.get("pageSize") != null ? Integer.parseInt(map.get("pageSize").toString()) : 10000;
        int current = map.get("current") != null ? Integer.parseInt(map.get("current").toString()) : 1;
        Page<PlatOrderPageRes> page = new Page<>(current,  size, false);
//        page.setSize(map.get("pageSize") != null ? Long.parseLong(map.get("pageSize").toString()) : 10);
//        page.setCurrent(map.get("current") != null ? Long.parseLong(map.get("current").toString()) : 1);
        return page;
    }

    // 处理单页数据
    private List<PlatformOrderNewExportVo> processPageData(List<PlatOrderPageRes> pageResList) {
        List<PlatformOrderNewExportVo> exportVos = new ArrayList<>();

        // 批量查询商品信息
        Map<Long, List<PlatformOrderProductDo>> collect = platformOrderProductDao.selectList(
                        new LambdaQueryWrapper<PlatformOrderProductDo>()
                                .in(PlatformOrderProductDo::getOrderId,
                                        pageResList.stream().map(PlatOrderPageRes::getId).collect(Collectors.toList())))
                .stream().collect(Collectors.groupingBy(PlatformOrderProductDo::getOrderId));
        //查詢商品信息
        List<Long> productIds = collect.values().stream().flatMap(Collection::stream).map(PlatformOrderProductDo::getProductId).distinct().collect(Collectors.toList());
        Map<Long, ProductDo> productDoMap = new HashMap<>();
        if (!productIds.isEmpty()) {
            List<ProductDo> productDos = productDao.selectList(new LambdaQueryWrapper<ProductDo>().select(ProductDo::getId, ProductDo::getJanCode, ProductDo::getItf, ProductDo::getSpu).in(ProductDo::getId, productIds));
            productDoMap = productDos.stream().collect(Collectors.toMap(ProductDo::getId, i -> i, (k1, k2) -> k1));
        }

        for (PlatOrderPageRes pageRes : pageResList) {
            StringBuilder address = new StringBuilder();
            if (StringUtils.isNotBlank(pageRes.getAddressOne())) {
                address.append(pageRes.getAddressOne());
            }
            if (StringUtils.isNotBlank(pageRes.getAddressTwo())) {
                address.append(pageRes.getAddressTwo());
            }
            if (StringUtils.isNotBlank(pageRes.getAddressTri())) {
                address.append(pageRes.getAddressTri());
            }

            List<PlatformOrderProductDo> productDos = collect.get(pageRes.getId());
            if (productDos == null || productDos.isEmpty()) {
                continue;
            }

            String japanChannelName = pageRes.getChannelCode();
            if ("yamato_zhai".equals(japanChannelName)) {
                japanChannelName = "ヤマト（宅急便）";
            } else if ("yamato_one".equals(japanChannelName) || "yamato_more".equals(japanChannelName)){
                japanChannelName = "ネコポス";
            }

            for (PlatformOrderProductDo productDo : productDos) {
                String orderTime = null;
                if (pageRes.getOrderTime() != null) {//pageRes.getOrderTime()
                    orderTime = DateUtils.dateFormatToString(pageRes.getOrderTime(), "yyyy-MM-dd HH:mm:ss");
                }
                String deliveryTimeName = StringUtils.isNotBlank(pageRes.getDeliveryTimeName()) ? "'" + pageRes.getDeliveryTimeName() : null;
                PlatformOrderNewExportVo exportVo = new PlatformOrderNewExportVo(
                        pageRes.getPlatformOrderNo(),
                        pageRes.getStoreName(),
                        japanChannelName,
                        pageRes.getReceiver(),
                        pageRes.getPostcode(),
                        pageRes.getDistrict(),
                        pageRes.getCityCode(),
                        address.toString().replaceAll(",", ""),
                        pageRes.getTelephone(),
                        pageRes.getDeliveryDate(),
                        deliveryTimeName,
                        pageRes.getTrackNo() != null ? pageRes.getTrackNo().replaceAll(",", ";") : null,
                        orderTime);
                ProductDo skuDo = productDoMap.get(productDo.getProductId());
                if (skuDo != null) {
                    exportVo.setJanCode(skuDo.getJanCode());
                    exportVo.setItf(skuDo.getItf());
                    exportVo.setSpu(skuDo.getSpu());
                }
                exportVo.setItemAmount(productDo.getItemAmount());
                exportVo.setPlatformSku(productDo.getPlatformSku());
                exportVo.setPlatformQty(productDo.getPlatformQty());
                exportVo.setSku(productDo.getSku());
                exportVo.setQty(productDo.getQty());

                if (StringUtils.isNotBlank(productDo.getPlatformProductName())) {
                    exportVo.setPlatformProductName(productDo.getPlatformProductName().replaceAll(",", ""));
                }

                exportVo.setDelvdateInfo(productDo.getDelvdateInfo());
                exportVos.add(exportVo);
            }
        }

        return exportVos;
    }

    // 下载导出文件
    @Override
    public void downloadExportFile(String taskId, HttpServletResponse response) {
        if (StringUtils.isBlank(taskId)) {
            throw new BizException(SysConstant.NoPower);
        }
        AsyncJobDo exportTask = asyncJobDao.selectById(taskId);

        if (exportTask == null || exportTask.getStatus() != 2) {
            throw new BizException("导出任务不存在或未完成");
        }
        String fileName = "注文データ_" + TimeUtils.getCurrentDateFormat("MMddHHmmss") + ".csv";
        try {
            // 设置响应头
//            response.setContentType("text/csv");
//            response.setContentType("application/vnd.ms-excel");
            response.setContentType("text/csv; charset=Shift-JIS");
            response.setCharacterEncoding("Shift-JIS");
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));

            // 输出文件内容
            CsvUtils.writeCsvToResponse(exportTask.getResultUrl(), response);

        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }

}




